package com.li.onjava8.concurrent.cf.exception;

import com.li.onjava8.concurrent.cf.task.Breakable;

import static com.li.onjava8.concurrent.cf.exception.CompletableExceptions.*;

/**
 * 加入或获取结果时，我们不会使用粗略的try-catch，而是使用CompletableFuture提供的更复杂的机制来自动响应异常
 * @author li
 * @date 2023/11/1 10:06
 */
public class CatchCompletableExceptions {

    static void handleException(int failcount) {
        //exceptionally: 返回一个新的CompletionStage，当这个阶段异常完成时，将使用这个阶段的异常作为所提供函数的参数来执行。
        //Exclusively()的局限性在于，该函数只能返回输入的相同类型的值。exclusively()通过将一个好的对象重新插入流中而恢复到可行状态。
        test("exceptionally", failcount)
                .exceptionally((ex) -> {
                    if (ex == null)
                        System.out.println("I don't get it yet");
                    return new Breakable(ex.getMessage(), 0);
                })
                .thenAccept(str -> System.out.println("result:" + str));


        //handle: 返回一个新的CompletionStage，当该阶段正常或异常完成时，将使用该阶段的结果和异常作为所提供函数的参数执行该阶段。
        //handle()始终被调用，你必须检查一下fail是否为true才能查看是否发生了异常。但是handle()可以产生任何新类型，因此它使你可以执行处理，而不仅可以像exception()那样进行恢复。
        test("handle", failcount)
                .handle((result, fail) -> {
                    if (fail != null)
                        return "Failure recovery object";
                    else
                        return result + "is good";
                })
                .thenAccept(str -> System.out.println("result" + str));


        //whenComplete: 返回一个新的 CompletionStage，其结果或异常与此阶段相同，该阶段完成时执行给定的操作。(将结果或异常传递下去)
        //whenComplete()就像handle()一样，你必须测试是否失败，但只是该参数是使用者，并且不会修改正在传递的结果对象。
        test("whenComplete", failcount)
                .whenComplete((result, fail) -> {
                    if (fail != null)
                        System.out.println("It Failed");
                    else
                        System.out.println(result + " OK");

                })
                .thenAccept(r -> System.out.println("result: " + r));
    }

    public static void main(String[] args) {
        System.out.println("**** Failure Mode ****");
        handleException(2);
        System.out.println("**** Success Mode ****");
        handleException(0);
    }




}
